/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package server;

import common.model.message.CreateMessage;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.StringTokenizer;
import java.util.Vector;

/**
 *
 * @author nicolas
 */
public class ServerHandler extends Thread {

    private Socket clientSock;    // client details
    private String cliAddr;
    private int port;
    private VisitorsGroup visitorsGroup;    // shared by all threads

    public ServerHandler(Socket s, VisitorsGroup visitorsGroup) {
        this.visitorsGroup = visitorsGroup;
        clientSock = s;
        cliAddr = clientSock.getInetAddress().getHostAddress();
        port = clientSock.getPort();
        System.out.println("Client connection from (" +
                cliAddr + ", " + port + ")");
    } // end of ChatServerHandler()

    public void run() {
        try {
            // Get I/O streams from the socket
            BufferedReader in = new BufferedReader(
                    new InputStreamReader(clientSock.getInputStream()));
            PrintWriter out =
                    new PrintWriter(clientSock.getOutputStream(), true);  // autoflush

            visitorsGroup.addPerson(cliAddr, port, out);  // add client details to Group

            processClient(in, out);            // interact with client

            // the client has finished when execution reaches here
            visitorsGroup.delPerson(cliAddr, port);       // remove client details
            clientSock.close();
            System.out.println("Client (" + cliAddr + ", " + port + ") connection closed\n");
            //visitorsGroup.getGuideManager().removeGuide();
        } catch (Exception e) {
            System.out.println(e);
        }
    }  // end of run()

    private void processClient(BufferedReader in, PrintWriter out) /* Stop when the input stream closes (is null) or "bye" is sent
    Otherwise pass the input to doRequest(). */ {
        String line;
        boolean done = false;
        try {
            while (!done) {
                if ((line = in.readLine()) == null) {
                    done = true;
                } else {
                    System.out.println("Client (" + cliAddr + ", " +
                            port + "): " + line);
                    if (line.trim().equals("bye")) {
                        done = true;
                    } else {
                        doRequest(line, out);
                    }
                }
            }
        } catch (IOException e) {
            System.out.println(e);
        }
    }  // end of processClient()

    private void doRequest(String line, PrintWriter out) /*  The input line (client message) can be :
    who				-- a list of users is returned
    or	any text		-- which is broadcast with
    (cliAddr,port) at its front
     */ {
        if (line.trim().contains("CREATE")) {
            //Register name
            Vector<Object> elems = this.quickTokenizer(line);
            visitorsGroup.registerUserName((String) elems.get(1), cliAddr, port);
            
            //Broadcast for all
            visitorsGroup.broadcast("(" + cliAddr + ", " + port + "): " + line);
        } else if (line.trim().contains("DETAILSFOR")) {
            //Message must be sent only to the person concerned, not everybody
            Vector<Object> elems = this.quickTokenizer(line);
            visitorsGroup.sendMessageToClient((String) elems.get(2), line);
        } else if (line.trim().contains("GUIDE")) {
            Vector<Object> elems = this.quickTokenizer(line);
            if (Boolean.parseBoolean(String.valueOf(elems.get(2))) == true) {
                visitorsGroup.getGuideManager().addGuide(String.valueOf(elems.get(1)));
            } else {
                visitorsGroup.getGuideManager().removeGuide(String.valueOf(elems.get(1)));
            }
        } else // use ChatGroup object to broadcast the message
        {
            visitorsGroup.broadcast("(" + cliAddr + ", " + port + "): " + line);
        }
    }  // end of doRequest()

    /**
     * Parse a command and stores elements in a vector
     * Maybe should be elsewhere
     * @param cmd
     * @return
     */
    private Vector<Object> quickTokenizer(String cmd) {
        StringTokenizer st = new StringTokenizer(cmd, " ");
        Vector<Object> elems = new Vector();
        while (st.hasMoreElements()) {
            elems.add(st.nextElement());
        }
        return elems;
    }
}
